/**
 * 公共方法、属性
 */

"use strict";
import layer from "layer-mobile";
//  ajax请求前缀

var ajaxPrefix = "http://api.jshrdtz.com";
// var ajaxPrefix = "http://m.finance.com:9091";

const Util = {
    //接口
    ajax: {
        //    是否登录
        isLogin: ajaxPrefix + "/api/register/isLogin",
        //    发送注册验证码
        sendsms: (mobile) => `${ajaxPrefix}/api/register/send/${mobile}`,
        //发送验证码token
        smsToken: `${ajaxPrefix}/api/register/smsToken`,
        //注册
        register: `${ajaxPrefix}/api/register`,
        //    理财产品列表
        product: `${ajaxPrefix}/api/product`,
        //理财产品详情
        productInfo: (id) => `${ajaxPrefix}/api/product/info/${id}`,
        //    客服列表
        customerService: `${ajaxPrefix}/api/customerService`,
        //    判断用户是否有投资
        haveInvests: `${ajaxPrefix}/api/custInvest/haveInvests`,
        //    我的产品列表
        custInvestList: `${ajaxPrefix}/api/custInvest`,
        //    我的理财详情
        investView: (id) => `${ajaxPrefix}/api/custInvest/view/${id}`,
        //    车辆文字转化
        CarType: `${ajaxPrefix}/api/enums/CarType`,
        //获取背景图片
        registBg: `${ajaxPrefix}/api/register/registBg`

    },


    /**
     * 验证手机号是否合法
     * @param mobile 手机号
     * @returns {boolean}
     */
    checkMobile: function (mobile) {
        //var YD = /^[1]{1}(([3]{1}[4-9]{1})|([5]{1}[012789]{1})|([8]{1}[12378]{1})|([4]{1}[7]{1}))[0-9]{8}$/;
        //
        //var LT = /^[1]{1}(([3]{1}[0-2]{1})|([5]{1}[56]{1})|([8]{1}[56]{1}))[0-9]{8}$/;
        //
        //var DX = /^[1]{1}(([3]{1}[3]{1})|([5]{1}[3]{1})|([8]{1}[09]{1}))[0-9]{8}$/;
        //
        ////特殊 177开头
        //var SP = /^[1]{1}(([7]{1}[7]{1}))[0-9]{8}$/;
        //return mobile && mobile.length == 11 && (YD.test(mobile) || LT.test(mobile) || DX.test(mobile) || SP.test(mobile));
        return mobile && /^[1]\d{10}$/.test(mobile);
    },

    /**
     * 判断对象中指定的属性是否都存在
     * @param obj       被判断的对象
     * @param property  属性值(字符串/数组)
     */
    isExits: function (obj, property) {
        var flag = true;
        if (this.getType(obj) == "object") {
            if (this.getType(property) == "array") {
                angular.forEach(property, function (item, key) {
                    if (!(item in obj)) {
                        flag = false;
                        return;
                    }
                });
            } else if (this.getType(property) == "string") {
                flag = property in obj;
            }
        } else {
            throw "the method Util.isExits need the first argument which typeof object!";
        }
        return flag;
    },

    /**
     * 检测身份证是否合法
     * @param idNum 身份证号
     * @returns {boolean}
     */
    checkId: function (idNum) {
        return (/^[\d]{15}$/).test(idNum) || (/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/gi).test(idNum);
    },

    /**
     * 检测邮箱是否合法
     * @param email 邮箱号
     * @returns {RegExp}
     */
    checkEmail: function (email) {
        return (/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/).test(email);
    },


    /**
     * 根据具体的键值(有或没有)返回该元素在数组中的位置
     * @param data  被循环的数组
     * @param id    用于判断是否包含的项
     * @param attr  如果数组项是对象,用来判断是否包含此键
     * @returns {number}
     */
    findIndex: function (data, id, attr) {
        var index = -1;
        data.forEach((item, key) => {
            if (attr) {
                if (item[attr] === id) {
                    index = key;
                }
            } else {
                if (item === id) {
                    index = key;
                }
            }
        });
        return index;
    },

    /**
     * 根据不同的键值判断是否有相同的并且返回本项
     * @param objArr    被循环的数组
     * @param key       用来判断的键
     * @param val       用来判断的值
     * @returns {*}
     */
    getItem: function (objArr, key, val) {
        return objArr.filter(function (item) {
            return item[key] == val;
        });
    },

    /**
     * 获取对象类型
     * @param object    被判断的对象
     * @returns {string}
     */
    getType: function (object) {
        return _typeOf(object).toLowerCase();
    },

    /**
     * 合并两个对象到第一个对象
     * @param obj1
     * @param obj2
     */
    merge: function (obj1, obj2) {
        var mergeRes;
        if (this.getType(obj1) == "object" && this.getType(obj2) == "object") {
            for (var i in obj2) {
                obj1[i] = obj2[i];
            }
            mergeRes = obj1;
        } else {
            mergeRes = obj1 || obj2;
        }
        return mergeRes;
    },

    /**
     * 判断两个值是否相等
     * @param value1    第一个值
     * @param value2    第二个值
     * @param type      是否判断类型boolean/object
     * @returns {boolean}
     */
    isEqual: function (value1, value2, type) {
        var equalFlag = false;
        if (this.getType(type) == "boolean" || !type) {
            equalFlag = type ? value1 === value2 : value1 == value2;
        } else if (this.getType(type) == "object") {
            for (var i in type) {
                equalFlag = (value1[i] == type[i] && value2[i] == type[i]);
                if (!equalFlag) {
                    break;
                }
            }
        }
        return equalFlag;
    },

    /**
     * 判断该对象是否有效(有效就返回对象,无效就不返回)
     * @param obj
     * @returns {*}
     */
    checkValid: function (obj) {
        if (obj || ("" + obj).length) {
            return obj;
        }
    },

    /**
     * 生成随机字符串
     * @returns {string}
     */
    randomStr: function () {
        return Math.random().toString(32).slice(2);
    },

    /**
     * 密码强度检测
     * @param password
     */
    checkPwdStrength: function (password) {
        var score = passwordCheck(password);
        return (score > 80) ? "strong" : (score > 60) ? "good" : (score > 30) ? "week" : "";
    },
    /**
     * 密码格式检测
     * @param password
     */
    checkPwd: function (password) {
        var reg = /^[0-9a-zA-Z]{6,16}$/;
        return password && reg.test(password);
    },
    /**
     * 读取input中的file生成form数据用于ajax提交
     * @param ele
     * @param data
     * @param limit
     * @returns {FormData}
     */
    generateFileForm: function (ele, data, limit) {
        var form = new FormData(),
            file = ele.files[0],
            size = ele.files[0].size;
        if (limit == true) {
            if (size > 500 * 1024) {
                layer.msg("上传大小不能大于" + 500 + "KB!");
                return;
            }
        }
        //form = this.merge(form, data);
        form.enctype = "multipart/form-data";
        form.append("image", file);
        console.dir(form);//

        if (_typeOf(data) === "Object") {
            angular.forEach(data, function (val, key) {
                form.append(key, val);
            });
        }
        return form;
    },

    /**
     * deep loop an object/Array
     * @param obj
     * @param sub
     * @param fn
     */
    deepLoop: function (obj, sub, fn) {
        var directLoop = arguments.length === 2 && this.getType(sub) === "function";
        var loopChild = arguments.length === 3 && this.getType(sub) === "string" && this.getType(fn) === "function";
        angular.forEach(obj, function (val, key) {
            if (directLoop) {
                sub(val, key, obj);
            } else if (loopChild) {
                fn(val, key, obj);
                if (val[sub]) {
                    angular.forEach(val[sub], function (valChild, keyChild) {
                        fn(valChild, keyChild, val[sub]);
                    });
                }
            }
        });
    },

    /**
     * math calculate methods
     */
    Math: {

        /**
         * add method
         * @param num1
         * @param num2
         * @returns {number}
         */
        add: function (num1, num2) {
            var r1, r2, m;
            try {
                r1 = num1.toString().split('.')[1].length;
            } catch (e) {
                r1 = 0;
            }
            try {
                r2 = num2.toString().split(".")[1].length;
            } catch (e) {
                r2 = 0;
            }
            m = Math.pow(10, Math.max(r1, r2));
            return Math.round(num1 * m + num2 * m) / m;
        },

        /**
         * sub menthod
         * @param num1
         * @param num2
         * @returns {Number}
         */
        sub: function (num1, num2) {
            var r1, r2, m, n;
            try {
                r1 = num1.toString().split('.')[1].length;
            } catch (e) {
                r1 = 0;
            }
            try {
                r2 = num2.toString().split(".")[1].length;
            } catch (e) {
                r2 = 0;
            }
            m = Math.pow(10, Math.max(r1, r2));
            n = (r1 >= r2) ? r1 : r2;
            return parseFloat((Math.round(num1 * m - num2 * m) / m).toFixed(n));
        },

        /**
         * mul method
         * @param num1
         * @param num2
         * @returns {number}
         */
        mul: function (num1, num2) {
            var m = 0, s1 = num1.toString(), s2 = num2.toString();
            try {
                m += s1.split(".")[1].length
            } catch (e) {
            }
            try {
                m += s2.split(".")[1].length
            } catch (e) {
            }
            return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
        },

        /**
         * div method
         * @param num1
         * @param num2
         * @returns {number}
         */
        div: function (num1, num2) {
            var t1, t2, r1, r2;
            try {
                t1 = num1.toString().split('.')[1].length;
            } catch (e) {
                t1 = 0;
            }
            try {
                t2 = num2.toString().split(".")[1].length;
            } catch (e) {
                t2 = 0;
            }
            r1 = Number(num1.toString().replace(".", ""));
            r2 = Number(num2.toString().replace(".", ""));
            return (r1 / r2) * Math.pow(10, t2 - t1);
        }

    },

    /**
     * 序列化数据
     */
    serialize: _serializenData,

    //  obverser object
    obsever: new Obsever(),
    //    弹出层提示信息
    tips: function (opt) {
        layer.open({
            type: 1,
            content: opt.content,
            skin: "msg",
            time: 1.5,
            anim: "up",
            success: function () {
                Util.getType(opt.success) == "function" && opt.success();
            }

        })
    }

};

export default Util

/**
 * check password strength
 * @param pass
 * @returns {*}
 */
function passwordCheck(pass) {
    var score = 0, variationCount;
    if (!pass) {
        return score;
    }

    var letters = new Object();
    for (var i = 0; i < pass.length; i++) {
        letters[pass[i]] = (letters[pass[i]] || 0) + 1;
        score += 5.0 / letters[pass[i]];
    }

    var variations = {
        digits: /\d/.test(pass),
        lower: /[a-z]/.test(pass),
        upper: /[A-Z]/.test(pass),
        nonWords: /\W/.test(pass),
    };

    variationCount = 0;
    for (var check in variations) {
        variationCount += (variations[check] == true) ? 1 : 0;
    }
    score += (variationCount - 1) * 10;

    return parseInt(score);
}

/**
 * simply write of encodeURIComponent
 * @param data
 * @returns {string}
 * @private
 */
function _encode(data) {
    data = data || "";
    return encodeURIComponent(data);
}

/**
 * serialize an object to an encoded url string to post
 * @param data  Object
 * @returns {string}
 * @private
 */
function _serializenData(data) {
    var res = data,
        typeIn;
    if (_typeOf(data) === "Object") {
        res = [];
        for (var i in data) {
            typeIn = _typeOf(data[i]);
            switch (typeIn) {

                //  two refrence type(Object/Array) need to loop them and push the return value to the result array
                case "Object":
                    res.push(_encode(_loopObject(data[i], i)));
                    break;

                case "Array":
                    res.push(_encode(_loopArray(data[i], i)));
                    break;

                //  not Object/Array type direct push to the result array
                default:
                    res.push(_encode(i) + "=" + _encode(data[i]));
                    break;

            }
        }
        res = res.join("&").replace("%20", "+")
    }
    return ("" + res);
}

/**
 * deep loop an array, tranfer to an string as return value
 */
function _loopArray(array, key) {
    var res = [],
        typeIn;
    for (var i = 0, len = array.length; i < len; i++) {
        typeIn = _typeOf(array[i]);
        switch (typeIn) {

            //  two refrence type(Object/Array) need to loop them and push the return value to the result array
            case "Array":
                res.push(_encode(_loopArray(array[i], (key + "[" + i + "]"))));
                break;

            case "Object":
                res.push(_encode(_loopObject(array[i], (key + "[" + i + "]"))));
                break;

            //  not Object/Array type direct push to the result array
            default:
                res.push(_encode(key + "[]" + "=" + array[i]));
                break;

        }
    }
    return res.join("&");
}

/**
 * deep loop an object, tranfer to an string as return value
 */
function _loopObject(object, key) {
    var res = [],
        typeIn;
    for (var i in object) {
        typeIn = _typeOf(object[i]);
        switch (typeIn) {
            //  two refrence type(Object/Array) need to loop them and push the return value to the result array
            case "Array":
                res.push(_loopArray(object[i], key + "[" + i + "]"));
                break;

            case "Object":
                res.push(_loopObject(object[i], key + "[" + i + "]"));
                break;

            //  not Object/Array type direct push to the result array
            default:
                res.push(_encode(key + "[" + i + "]" + "=" + object[i]));
                break;
        }
    }
    return res.join("&");
}

/**
 * get Prototype classname on object
 * @param obj
 * @returns {ArrayBuffer|Array.<T>|string|Blob|*}
 * @private
 */
function _typeOf(obj) {
    return {}.toString.call(obj).slice(8, -1);
}

/**
 * pub/sub模型
 * @private
 */
function Obsever() {
    this.eventList = [];
}


Obsever.prototype.sub = function (ev, fn) {
    this.eventList.push({
        name: ev,
        fn: fn
    });
};

Obsever.prototype.pub = function (ev, arg) {
    this.eventList.forEach(function (item) {
        (item.name === ev) && item.fn.apply(angular, arg || []);
    });
};
